package searchlogic

import "sort"

type MatchPos struct {
	from int
	to   int
}

type CombinedSearchResultItem struct {
	titleHasKeyword     bool
	titleKeywordPoses   []MatchPos
	contentHasKeyword   bool
	contentKeywordPoses []MatchPos
	mapInfo             *MindMapInfo
}

// 把对同一个导图文件的多个表达式的匹配结果进行合并，比如匹配位置的重叠处理等
func combine(resultItems []SearchResultItem) *CombinedSearchResultItem {

	result := &CombinedSearchResultItem{
		mapInfo:             resultItems[0].MapInfo,
		titleKeywordPoses:   make([]MatchPos, 0, 2),
		contentKeywordPoses: make([]MatchPos, 0, 2),
	}

	filt := func(filterFun func(item *SearchResultItem) bool, sortFun func(item1 *SearchResultItem, item2 *SearchResultItem) bool) []SearchResultItem {
		ret := make([]SearchResultItem, 0, 2)
		for _, item := range resultItems {
			if filterFun(&item) {
				ret = append(ret, item)
			}
		}
		sort.Slice(ret, func(i, j int) bool {
			return sortFun(&ret[i], &ret[j])
		})
		return ret
	}

	// 标题匹配项处理
	tmpInd := -1
	titleMatchItems := filt(func(item *SearchResultItem) bool {
		return item.TitleHasKeyword
	}, func(item1 *SearchResultItem, item2 *SearchResultItem) bool {
		return item1.TitleKeywordPosFrom < item2.TitleKeywordPosFrom
	})
	for _, item := range titleMatchItems {
		result.titleHasKeyword = true

		// 还未记录过匹配区间，增加一个
		if tmpInd < 0 {
			result.titleKeywordPoses = append(result.titleKeywordPoses, MatchPos{
				from: item.TitleKeywordPosFrom,
				to:   item.TitleKeywordPosTo,
			})
			tmpInd = len(result.titleKeywordPoses) - 1
			continue
		}

		// 记录过匹配区别，且当前区间与上一次记录的区间可以连接成一个
		if item.TitleKeywordPosFrom <= result.titleKeywordPoses[tmpInd].to {
			if item.TitleKeywordPosTo > result.titleKeywordPoses[tmpInd].to {
				result.titleKeywordPoses[tmpInd].to = item.TitleKeywordPosTo
			}
			continue
		}

		// 记录过匹配区别，且当前区间与上一个记录的区间没有重叠，则新增一个区间
		result.titleKeywordPoses = append(result.titleKeywordPoses, MatchPos{
			from: item.TitleKeywordPosFrom,
			to:   item.TitleKeywordPosTo,
		})
		tmpInd = len(result.titleKeywordPoses) - 1
	}

	// 正文匹配项处理
	tmpInd = -1
	contMatchItems := filt(func(item *SearchResultItem) bool {
		return item.ContentHasKeyword
	}, func(item1 *SearchResultItem, item2 *SearchResultItem) bool {
		return item1.ContentKeywordPosFrom < item2.ContentKeywordPosFrom
	})
	for _, item := range contMatchItems {
		result.contentHasKeyword = true

		if tmpInd < 0 {
			result.contentKeywordPoses = append(result.contentKeywordPoses, MatchPos{
				from: item.ContentKeywordPosFrom,
				to:   item.ContentKeywordPosTo,
			})
			tmpInd = len(result.contentKeywordPoses) - 1
			continue
		}

		if item.ContentKeywordPosFrom <= result.contentKeywordPoses[tmpInd].to {
			if item.ContentKeywordPosTo > result.contentKeywordPoses[tmpInd].to {
				result.contentKeywordPoses[tmpInd].to = item.ContentKeywordPosTo
			}
			continue
		}

		result.contentKeywordPoses = append(result.contentKeywordPoses, MatchPos{
			from: item.ContentKeywordPosFrom,
			to:   item.ContentKeywordPosTo,
		})
		tmpInd = len(result.contentKeywordPoses) - 1
	}
	return result
}
